package com.iteaj.network.codec;

import com.iteaj.network.AbstractMessage;
import com.iteaj.network.ProtocolException;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandler;
import org.springframework.beans.BeanUtils;

import java.lang.reflect.Constructor;

/**
 * 报文{@link AbstractMessage}解码器
 * 使用此解码器务必保留默认的报文构造函数{@link AbstractMessage#AbstractMessage(byte[])}
 */
public interface IotMessageDecoder extends ChannelInboundHandler {

    Class<? extends AbstractMessage> getMessageClass();

    IotMessageDecoder setMessageClass(Class<? extends AbstractMessage> messageClass);

    /**
     * 使用默认的构造函数 {@link AbstractMessage#AbstractMessage(byte[])} 构造实体报文
     * @param ctx
     * @param decode 可以是类型 ByteBuf、AbstractMessage、null
     * @return AbstractMessage 使用默认的构造函数 {@link AbstractMessage#AbstractMessage(byte[])}
     * @throws Exception
     */
    default AbstractMessage proxy(ChannelHandlerContext ctx, ByteBuf decode) throws Exception {
        if(decode != null) {
            AbstractMessage message = doDecode(ctx, decode);
            if(message != null) {
                return message.build();
            } else {
                return null;
            }
        } else {
            return null;
        }
    }

    /**
     * 默认的解码
     * 使用默认构造器创建报文 {@link AbstractMessage#AbstractMessage(byte[])}
     * @param ctx
     * @param decode
     * @return
     */
    default AbstractMessage doDecode(ChannelHandlerContext ctx, ByteBuf decode) {
        int readableBytes = (decode).readableBytes();
        if(readableBytes <= 0) return null;

        byte[] message = new byte[readableBytes];
        (decode).readBytes(message);

        // 报文必须保留默认的构造函数
        try {
            return BeanUtils.instantiateClass(getMessageClass().getConstructor(byte[].class), message);
        } catch (Exception e) {
            throw new ProtocolException("找不到构造函数["+getMessageClass().getSimpleName()+"(byte[])], 请增加对应的构造函数或者自定义解码", e.getCause());
        }
    }
}
